import java.util.Scanner;

//字符串常量池 -- 底层是一个StringTable的哈希表
public class Test {
    public static void main1(String[] args) {
        String str1 = "abcd"; //""引起来的存储在常量池，常量池中只会存储一份
        String str2 = "abcd";
        String str3 = new String("abcd");
        String str4 = new String("abcd");

        System.out.println(str1 == str2);
        System.out.println(str3 == str4);
        System.out.println(str1 == str3);
    }

    public static void main2(String[] args) {
        char[] ch = new char[]{'a', 'b', 'c'};
        String s1 = new String(ch); //s1对象并不在常量池当中
//        s1.intern(); //s1.intern()，调用之后会将s1对象放入到常量池当中
        String s2 = "abc";  //“abc”在常量池当中存在了，s2创建时直接用常量池中“abc”的引用
        System.out.println(s1 == s2); //false ，如果加上s1.intern();则结果为true
    }

    public static void main3(String[] args) {
        //final的正确理解
        final int[] arr = {1,2,3,4}; //被final修饰的变量它的指向不能修改，也就是它引用的对象时固定唯一的
//        arr = new int[10];  所以这里再去引用其他的那就是错误的
        arr[0] = 99; //但是可以修改它所指向的对象的内容
    }

    //最优的
    public static void main4(String[] args) {
        String str = "abcd";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(str);
        for (int i = 0; i < 100; i++) {
            stringBuilder.append(i);
        }
        System.out.println(stringBuilder);
    }

    public static void main5(String[] args) {
        String str = "abcd";
        for (int i = 0; i < 100; i++) {
            str += i;
        }
        System.out.println(str);
    }

    public static void main6(String[] args) {
        String str = "abcd";
        for (int i = 0; i < 100; i++) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(str);
            stringBuilder.append(i);
            str = stringBuilder.toString();
        }
        System.out.println(str);
    }

    public static void main7(String[] args) {
        //可变的对象
        StringBuilder stringBuilder = new StringBuilder("hello");
        stringBuilder.append("abcd");
        System.out.println(stringBuilder);

        //逆置
        stringBuilder.reverse();
        System.out.println(stringBuilder);

        String s = stringBuilder.toString();
        System.out.println(s);

        //把stringBuilder对象 转变成String对象 -- 调用toString()
        String s1 = stringBuilder.toString();
        System.out.println(s1);
        //把String对象 转变成stringBuilder对象 -- 创建对象
        String x = "world";
        StringBuilder stringBuilder1 = new StringBuilder(x);
        System.out.println(stringBuilder1);
    }

    /**387 字符串中的第一个唯一字符:给定一个字符串 s ，找到 它的第一个不重复的字符，并返回它的索引 。如果不存在，则返回 -1 */
    public int firstUniqChar(String s) {
        int[] count = new int[26];
        for(int i = 0; i < s.length(); i++){
            char ch = s.charAt(i); //charAt(i)返回i下标的值
            count[ch - 'a']++;
        }
        for(int i = 0; i < s.length(); i++){
            char ch = s.charAt(i);
            if(count[ch - 'a'] == 1){
                return i;
            }
        }
        return -1;
    }

    /**字符串最后一个单词的长度
    计算字符串最后一个单词的长度，单词以空格隔开，字符串长度小于5000。（注：字符串末尾不以空格为结尾）
    输入描述：输入一行，代表要计算的字符串，非空，长度小于5000。
    输出描述：输出一个整数，表示输入字符串最后一个单词的长度。*/
    //方法1：
    public void lastLength(){
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        int pos = str.lastIndexOf(" ");//返回指定字符(本题中指空格)的最后一次出现的字符串中的索引
        System.out.println(str.length() - 1 - pos);
    }
    //方法2：
    public void lastLength2(String s){
        int index = -1;
        for(int i = s.length()-1; i > 0; i--){
            if(s.charAt(i) == ' '){
                index = i;
            }
        }
        System.out.println(s.length() - 1 - index);
    }
    //方法3：
    public void lastLength3(String s){
        String[] str = s.split(" "); //以空格分隔开，str现在是一个字符串数组
        System.out.println(str[str.length - 1].length()); //str.length-1是数组的最后一个下标，
        // str[str.length - 1]是数组最后一个元素，因为最后一个元素也是一个字符串，所以再引用length()即可求出长度
    }

    /**验证回文串
     如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后，短语正着读和反着读都一样。则可以认为该短语是一个回文串 。
     字母和数字都属于字母数字字符。给你一个字符串 s，如果它是 回文串 ，返回 true ；否则，返回 false 。
     示例 1：输入: s = "A man, a plan, a canal: Panama"  输出：true
     解释："amanaplanacanalpanama" 是回文串。*/
    public boolean isEffective(char ch){ //判断字符是否有效
        if(Character.isLetter(ch) || Character.isDigit(ch)){
            return true;
        }
        return false;
    }
    public boolean isPalindrome(String s) {
        s = s.toLowerCase();
        int left = 0;
        int right = s.length() - 1;
        while(left < right){
            //如果左边字符不是有效字符，则继续++，直到找到有效字符
            while(left < right && !isEffective(s.charAt(left))){
                left++;
            }
            //如果右边字符不是有效字符，则继续--，直到找到有效字符
            while(left < right && !isEffective(s.charAt(right))){
                right--;
            }
            if(s.charAt(left) != s.charAt(right)){
                return false;
            }else {
                left++;
                right--;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        Test test = new Test();
//        System.out.println(test.firstUniqChar("leetcode")); //0

//        test.lastLength();
//        test.lastLength2("hello world!");
//        test.lastLength3("hello world!");\

        System.out.println(test.isPalindrome("A man, a plan, a canal: Panama"));
    }
}

